﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TSOL.FastSPWeb.ValueObjects;
using System.Threading;
using Microsoft.SharePoint;

namespace TSOL.FastSPWeb.Core
{
    internal partial class FastSPItemUpdateThreadWorkerQueue : IDisposable
    {
        internal long WaitingForThread = 0;
        internal int UpdateTries = 10;
        internal int MaxNumberOfThreads = 255;
        internal int StartedThreads = 0;
        object locker = new object();
        internal Thread[] workers;
        internal Queue<BaseFastSPActionQueue> taskQ = new Queue<BaseFastSPActionQueue>();


        internal static void Create(int threadCount)
        {
            FastSPWebThreadWorkerQueue.GlobalSPItemUpdateThreadWorkerQueue = new FastSPItemUpdateThreadWorkerQueue(threadCount);
        }

        internal void StartThreads(int threadCount)
        {
            int startedThreads = workers.Count(a => a.ThreadState != ThreadState.Unstarted);

            int threadsToStart = threadCount - startedThreads;

            foreach (Thread unstartedThread in workers)
            {
                if (threadsToStart < 1)
                    break;

                if (unstartedThread.ThreadState == ThreadState.Unstarted)
                {
                    unstartedThread.Start();
                    threadsToStart--;
                }
            }
            StartedThreads = FastSPWebThreadWorkerQueue.GlobalSPItemUpdateThreadWorkerQueue.workers.Count(a => a.ThreadState != ThreadState.Unstarted);
        }

        FastSPItemUpdateThreadWorkerQueue(int threadCount)
        {
            if (threadCount > MaxNumberOfThreads) threadCount = MaxNumberOfThreads;
            if (threadCount < 1) threadCount = 1;

            workers = new Thread[MaxNumberOfThreads];
            for (int i = 0; i < MaxNumberOfThreads; i++)
                workers[i] = new Thread(ConsumeSPItemUpdateTasks);

            for (int i = 0; i < threadCount; i++)
                workers[i].Start();

            StartedThreads = threadCount;
        }

        public void Dispose()
        {
            foreach (Thread worker in workers)
            {
                if (worker.ThreadState != ThreadState.Unstarted)
                    StopQueue();
            }
        }

        void ConsumeSPItemUpdateTasks()
        {
            while (true)
            {
                BaseFastSPActionQueue task;
                lock (locker)
                {
                    while (taskQ.Count == 0) Monitor.Wait(locker);
                    task = taskQ.Dequeue();
                }
                if (task.Action == FastUpdateAction.StopQueue) return;         // Application is disposing

                switch (task.Action)
                {
                    case FastUpdateAction.Update:
                        UpdateSPItem((FastSPItemQueueClass)task);
                        break;

                    case FastUpdateAction.CreateSubWeb:
                        CreateSubWeb((FastCreateSubWebQueueClass)task);
                        break;
                }
            }
        }
    }
}
